package com.example.clipsync;

import android.util.Log;

import org.json.JSONObject;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

import de.robv.android.xposed.XposedBridge;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;

/**
 * WebSocket 管理器类
 * 用于管理剪贴板内容的WebSocket连接和消息发送
 */
public class WsManager {
    // 日志标签
    private static final String TAG = "GlobalClipboardLS";
    // 单例实例
    private static volatile WsManager instance = null;

    // WebSocket服务器URL
    private final String url;
    // OkHttp客户端
    private final OkHttpClient client;
    // WebSocket连接对象
    private volatile WebSocket webSocket;
    // 消息队列，用于存储待发送的剪贴板内容
    private final LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>(1024);
    // 运行状态标志
    private volatile boolean running = true;
    // 工作线程，负责处理消息发送和连接管理
    private final Thread worker;

    /**
     * 私有构造方法，初始化WebSocket管理器
     * @param url WebSocket服务器地址
     */
    private WsManager(String url) {
        this.url = url;
        this.client = new OkHttpClient.Builder()
                .connectTimeout(5, TimeUnit.SECONDS)
                .readTimeout(0, TimeUnit.MILLISECONDS) // 保持连接
                .retryOnConnectionFailure(true)
                .build();
        this.worker = new Thread(this::runLoop, "ClipSync-WsManager");
        this.worker.setDaemon(true);
        this.worker.start();
    }

    /**
     * 启动或重启WebSocket管理器
     * @param url WebSocket服务器URL
     */
    public static synchronized void startOrRestart(String url) {
        if (instance != null) {
            instance.shutdown();
        }
        XposedBridge.log(TAG + ": 启动 WsManager，连接地址: " + url);
        instance = new WsManager(url);
    }

    /**
     * 停止当前运行的WebSocket管理器
     */
    public static synchronized void stop() {
        if (instance != null) {
            XposedBridge.log(TAG + ": 停止 WsManager.");
            instance.shutdown();
            instance = null;
        } else {
            XposedBridge.log(TAG + ": WsManager 未运行.");
        }
    }

    /**
     * 获取WebSocket管理器实例
     * @return WsManager实例，如果未启动则为null
     */
    public static synchronized WsManager getInstance() {
        return instance;
    }

    /**
     * 关闭WebSocket管理器
     */
    private void shutdown() {
        this.running = false;
        if (worker != null) {
            worker.interrupt();
        }
        // 工作循环会检测到running=false并关闭socket
    }

    /**
     * 将剪贴板内容加入发送队列
     * @param text 要发送的文本内容
     */
    public void enqueueMessage(String text) {
        if (text == null) return;
        try {
            JSONObject json = new JSONObject();
            json.put("text", text);
            if (!queue.offer(json.toString())) {
                queue.poll();
                queue.offer(json.toString());
            }
        } catch (Throwable e) {
            XposedBridge.log(TAG + ": 加入消息队列时出错 -> " + Log.getStackTraceString(e));
        }
    }

    /**
     * 工作循环，负责处理WebSocket连接和消息发送
     */
    private void runLoop() {
        while (running) {
            try {
                if (webSocket == null) {
                    tryConnect();
                }

                String outbound = queue.poll(5, TimeUnit.SECONDS);
                if (outbound != null && webSocket != null) {
                    try {
                        webSocket.send(outbound);
                    } catch (Throwable e) {
                        XposedBridge.log(TAG + ": WebSocket发送失败 -> " + Log.getStackTraceString(e));
                        closeWebSocketSilently();
                    }
                }
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
                XposedBridge.log(TAG + ": 工作线程被中断，正在关闭.");
            } catch (Throwable t) {
                XposedBridge.log(TAG + ": WsManager运行循环出错 -> " + Log.getStackTraceString(t));
                try { Thread.sleep(2000); } catch (InterruptedException ignored) { Thread.currentThread().interrupt(); }
            }
        }
        closeWebSocketSilently();
        XposedBridge.log(TAG + ": WsManager工作线程已结束.");
    }

    /**
     * 尝试连接WebSocket服务器
     */
    private void tryConnect() {
        if (!running) return; // 如果正在关闭，则不尝试连接
        Request req = new Request.Builder().url(url).build();
        try {
            webSocket = client.newWebSocket(req, new WebSocketListener() {
                @Override
                public void onOpen(WebSocket ws, Response response) {
                    XposedBridge.log(TAG + ": WebSocket已打开.");
                }

                @Override
                public void onMessage(WebSocket ws, String message) {
                    try {
                        JSONObject json = new JSONObject(message);
                        String text = json.optString("text", "");

                        if (!text.isEmpty()) {
                            ClipboardUtils.writeToSystemClipboard(text);
                        }
                    } catch (Throwable e) {
                        XposedBridge.log(TAG + ": 解析消息出错 -> " + Log.getStackTraceString(e));
                    }
                }

                @Override
                public void onClosing(WebSocket ws, int code, String reason) {
                    XposedBridge.log(TAG + ": WebSocket正在关闭: " + reason);
                    try { ws.close(1000, null); } catch (Throwable ignored) {}
                }

                @Override
                public void onClosed(WebSocket ws, int code, String reason) {
                    XposedBridge.log(TAG + ": WebSocket已关闭: " + reason);
                    if (webSocket == ws) webSocket = null;
                }

                @Override
                public void onFailure(WebSocket ws, Throwable t, Response response) {
                    XposedBridge.log(TAG + ": WebSocket连接失败: " + Log.getStackTraceString(t));
                    if (webSocket == ws) webSocket = null;
                }
            });
        } catch (Throwable e) {
            XposedBridge.log(TAG + ": 尝试连接时发生异常 -> " + Log.getStackTraceString(e));
            webSocket = null;
            try { Thread.sleep(2000); } catch (InterruptedException ignored) { Thread.currentThread().interrupt(); }
        }
    }

    /**
     * 静默关闭WebSocket连接
     */
    private void closeWebSocketSilently() {
        try {
            if (webSocket != null) {
                webSocket.close(1000, "closing");
            }
        } catch (Throwable ignored) {}
        webSocket = null;
    }
}